// header defining supported endian types
#ifndef endian_h
#define endian_h

// all dependencies
#include "basic_types.h"
#include "mem_space.h"

// enum with supported endianness
typedef enum
{
  OWL_ENDIAN_UNKNOWN, // no endian (not supported)
  OWL_ENDIAN_BIG,     // big endian mode
  OWL_ENDIAN_LITTLE,  // little endian mode
} owl_endian;

// initialized to that for now, it is mandatory
// to execute the owl_check_sys_endia() funtion
// for all the other functions in this library
// to execute correctly
owl_endian OWL_SYS_ENDIAN = OWL_ENDIAN_UNKNOWN;

typedef enum
{
  OWL_TYPE_ENDIAN = OWL_TYPE_MEM_SPACE_ERR + 1,
} owl_type_endian_h;

// function to check the system current endianness
// Can only consider big and little endian systems
void owl_check_sys_endian(void)
{
  // no chance mate
  if (sizeof(owl_umax) < 4) /* I need at least a 4 byte integer type */ {
    printf("ENDIAN ERROR: MAX INTEGER TYPE SIZE UNDER 4 BYTES.\n");
    exit(1);
  }
  // check endianness
  owl_umax test = 0x00112233;  
  owl_byte * ptr = (void *) &test;
  if (ptr[sizeof(owl_umax) - 1] == 0x33
      && ptr[sizeof(owl_umax) - 2] == 0x22
      && ptr[sizeof(owl_umax) - 3] == 0x11
      && ptr[sizeof(owl_umax) - 4] == 0x00)
    OWL_SYS_ENDIAN = OWL_ENDIAN_BIG;
  else if (ptr[0] == 0x33
           && ptr[1] == 0x22
           && ptr[2] == 0x11
           && ptr[3] == 0x00)
    OWL_SYS_ENDIAN = OWL_ENDIAN_LITTLE;
  else /* wont allow program execution on an unknown endian system */ {
    printf("ENDIAN ERROR: UNKNOWN SYSTEM ENDIAN.\n");
    exit(1);
  }
}

// to check an endian integer
owl_bool owl_check_endian(owl_endian endian)
{
  return (endian == OWL_ENDIAN_BIG || endian == OWL_ENDIAN_LITTLE);
}

#endif // endian_h
